/**
 * File: ContainerFactory.java
 * Author: Eliana Feasley and Mark pallone
 * Emails: elf4@umbc.edu , markpa1@umbc.edu
 * Date: Jun 19, 2011
 * 
 * Description: Gives container options and produces Container objects upon request. 
 */
package data;

import java.util.ArrayList;
import model.*;

/**
 * @author mark
 *
 */
public class ContainerFactory {
	public static final String[] CONTAINER_OPTIONS = {"cup", "bowl", "cone", "bag"};
	public static final String[] SIZES = {"small", "medium", "large"};
	
	// indices into CONTAINER_OPTIONS
	public static final int CUP = 0;
	public static final int BOWL = 1;
	public static final int CONE = 2;
	public static final int BAG = 3;
	
	// indices into SIZES
	public static final int SMALL = 0;
	public static final int MEDIUM = 1;
	public static final int LARGE = 2;
	
	// container prices
	public static final double MEDIUM_SUGAR_CONE_COST = .50;
	public static final double MEDIUM_WAFFLE_CONE_COST = .75;
	public static final double MEDIUM_DOUBLE_HEADER_CONE_COST = .75;
	public static final double LARGE_COST_ADDITION = .50; // how much it costs to upgrade a cone to a large
	public static final double BOWL_COST = 0;
	public static final double SMALL_CUP_COST = 1.00;
	public static final double MEDIUM_CUP_COST = 1.50;
	public static final double LARGE_CUP_COST = 2.00;
	public static final double BAG_COST = 0.05;
	
	public static final String[] CONE_TYPES = {"sugar cone", "waffle cone", "double header cone"};
	public static final int SUGAR_CONE = 0;
	public static final int WAFFLE_CONE = 1;
	public static final int DOUBLE_HEADER_CONE = 2;


	/**
	 * 
	 * getContainerOptions - get a list of containers depending on the treat type 
	 * Preconditions: none
	 * Postconditions: a list of valid container options is returned
	 * @param treat the treat which needs a container
	 * @return list of valid container options
	 */
	public ArrayList<String> getContainerOptions(Treat treat) {
		ArrayList<String> options = new ArrayList<String>();
		
		if (treat instanceof IceCream) {
			options.add(CONTAINER_OPTIONS[BOWL]); 
			options.add(CONTAINER_OPTIONS[CONE]);  
		} else if (treat instanceof Sundae) {
			options.add(CONTAINER_OPTIONS[CUP]);
			options.add(CONTAINER_OPTIONS[BOWL]);
		} else if (treat instanceof Beverage) {
			options.add(CONTAINER_OPTIONS[CUP]);
		} else if (treat instanceof HashBrowns)	 {
			options.add(CONTAINER_OPTIONS[BAG]);
		} else if (treat instanceof Sandwich) {
			options.add(CONTAINER_OPTIONS[BAG]);
		} else if (treat instanceof Doughnut) {
			options.add(CONTAINER_OPTIONS[BAG]);
		} else if (treat instanceof Munchkins) {
			options.add(CONTAINER_OPTIONS[BAG]);
		} else if (treat instanceof Bagel) {
			options.add(CONTAINER_OPTIONS[BAG]);
		} else if (treat instanceof Muffin) {
			options.add(CONTAINER_OPTIONS[BAG]);
		}
		
		else { 
			// if no special rules, just add everything to the list 
			for (int i = 0; i < CONTAINER_OPTIONS.length; i++) {
				options.add(CONTAINER_OPTIONS[i]);
			}
		}
		
		return options;
	}
	
	/**
	 * 
	 * getConeOptions - get the cone options
	 * Preconditions: none
	 * Postconditions:  a list of valid cone options is returned
	 * @return a list of valid cone options
	 */
	public ArrayList<String> getConeOptions() {
		ArrayList<String> options = new ArrayList<String>();
		for (int i = 0; i < CONE_TYPES.length; i++) {
			options.add(CONE_TYPES[i]);
		}
		return options;
	}
	
	/**
	 * 
	 * getSizeOptions - get the options available for each type of container
	 * Preconditions: container must be an option in CONTAINER_OPTIONS
	 * Postconditions: a list of valid size options is returned
	 * @param container the container string, chosen from CONTAINER_OPTIONS
	 * @return a list of valid size options
	 * @throws Exception if the String container is not in CONTAINER_OPTIONS, this exception is thrown. 
	 */
	public ArrayList<String> getSizeOptions(String container) throws Exception {
		ArrayList<String> options = new ArrayList<String>();
		
		// return the options available for each type of container
		if (container.equals(CONTAINER_OPTIONS[CUP])) {
			options.add(SIZES[SMALL]);
			options.add(SIZES[MEDIUM]);
			options.add(SIZES[LARGE]);
		} else if (container.equals(CONTAINER_OPTIONS[BOWL])) {
			options.add(SIZES[SMALL]);
			options.add(SIZES[MEDIUM]);
			options.add(SIZES[LARGE]);
		} else if (container.equals(CONTAINER_OPTIONS[CONE])) {
			options.add(SIZES[MEDIUM]);
			options.add(SIZES[LARGE]);
		} else if (container.equals(CONTAINER_OPTIONS[BAG])) {
			options.add(SIZES[SMALL]);
		}
		
		else {
			throw new Exception("Unknown container type: '" + container + "'");
		}
		
		return options;
	}
	
	/**
	 * 
	 * getContainer - get a container object
	 * Preconditions: containerType must be an option within CONTAINER_OPTIONS or CONE_TYPES. Note that the 
	 * the string "cone" is treated as "sugar cone". 
	 * Postconditions: a container object will be returned
	 * @param containerType the type of the container, eg, "cone", "bowl" 
	 * @param size the size of the container
	 * @return
	 * @throws Exception 
	 */
	public Container getContainer(String containerType, String size) throws Exception {
		Container container = new Container(size, containerType, 0);
		
		// cone nonsense -_-
		if (containerType.equals(CONE_TYPES[SUGAR_CONE]) || containerType.equals(CONTAINER_OPTIONS[CONE])) {
			container.setPrice(MEDIUM_SUGAR_CONE_COST);
			if (size.equals(SIZES[LARGE])) {
				container.setPrice(container.getPrice() + LARGE_COST_ADDITION);
			}
		} else if (containerType.equals(CONE_TYPES[WAFFLE_CONE])) {
			container.setPrice(MEDIUM_WAFFLE_CONE_COST);
			if (size.equals(SIZES[LARGE])) {
				container.setPrice(container.getPrice() + LARGE_COST_ADDITION);
			}
		} else if (containerType.equals(CONE_TYPES[DOUBLE_HEADER_CONE])) {
			container.setPrice(MEDIUM_DOUBLE_HEADER_CONE_COST);
			if (size.equals(SIZES[LARGE])) {
				container.setPrice(container.getPrice() + LARGE_COST_ADDITION);
			}
		} // cup
		else if (containerType.equals(CONTAINER_OPTIONS[CUP])) {
			if (size.equals(SIZES[SMALL])) {
				container.setPrice(SMALL_CUP_COST);
			} else if (size.equals(SIZES[MEDIUM])) {
				container.setPrice(MEDIUM_CUP_COST);
			} else {
				container.setPrice(LARGE_CUP_COST);
			}
		} // bowl
		else if (containerType.equals(CONTAINER_OPTIONS[BOWL])) {
			container.setPrice(BOWL_COST);
		} // bag
		else if (containerType.equals(CONTAINER_OPTIONS[BAG])) {
			container.setPrice(BAG_COST);
		}
		
		else {
			throw new Exception("unknown container type: '" + containerType + "'");
		}
		
		return container;
	}
}
